#include <cppunit/config/SourcePrefix.h>
#include "Calls.h"
#include "TestCalls.h"

#include <algorithm>
#include <iostream>
#include <string>

void CallsTest::setUp()
{
	cout << "Test PKB Calls setUp()\n";
}
void CallsTest::tearDown()
{}
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( CallsTest ); 
// method to test the constructor
void CallsTest::testConstructor() { 
// create a Follow object
// check that the object is constructed correctly
//	Calls myCallsTable = Calls::Calls();
}
void CallsTest::testSetCalls(){
	std::cout<<std::endl<<"Testing setCalls..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,2,3);
	//CPPUNIT_ASSERT_EQUAL(2, myCallsTable.getCalledBy(1).back());
	CPPUNIT_ASSERT(myCallsTable.isCalls(1,3));
}

/*
procedure aaa{                  //procIndex 1
	call bbb;    //lineIndex 1
	call ccc;    //lineIndex 2
}
procedure bbb{                  //procIndex 2
	call aaa;    //lineIndex 3
	call ccc;    //lineIndex 4
}
procedure ccc{                  //procIndex 3
	call aaa;	 //lineIndex 5
	call bbb;    //lineIndex 6
}
*/


void CallsTest::testGetCalledBy(){
	std::cout<<std::endl<<"Testing getCalledBy..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,1,2);
	myCallsTable.setCalls(1,2,3);
	myCallsTable.setCalls(2,3,1);
	myCallsTable.setCalls(2,4,3);
	myCallsTable.setCalls(3,5,1);
	myCallsTable.setCalls(3,6,2);

	//Get called procedure by procedure 1
	Type::Index::Proc calledProcSamplec1[] = {2,3};
	Type::List::Proc calledProcListSample1 (calledProcSamplec1, calledProcSamplec1 + sizeof(calledProcSamplec1)/sizeof(Type::Index::Line));
	Type::List::Proc calledProcList1 = myCallsTable.getCalledBy(1);
	sort(calledProcList1.begin(),calledProcList1.end());
	CPPUNIT_ASSERT(calledProcListSample1 == calledProcList1);

	//Get called procedure by procedure 2
	Type::Index::Proc calledProcSamplec2[] = {1,3};
	Type::List::Proc calledProcListSample2 (calledProcSamplec2, calledProcSamplec2 + sizeof(calledProcSamplec2)/sizeof(Type::Index::Line));
	Type::List::Proc calledProcList2 = myCallsTable.getCalledBy(2);
	sort(calledProcList2.begin(),calledProcList2.end());
	CPPUNIT_ASSERT(calledProcListSample2 == calledProcList2);

	//Get called procedure by procedure 3
	Type::Index::Proc calledProcSamplec3[] = {1,2};
	Type::List::Proc calledProcListSample3 (calledProcSamplec3, calledProcSamplec3 + sizeof(calledProcSamplec3)/sizeof(Type::Index::Line));
	Type::List::Proc calledProcList3 = myCallsTable.getCalledBy(3);
	sort(calledProcList3.begin(),calledProcList3.end());
	CPPUNIT_ASSERT(calledProcListSample3==calledProcList3);

}
void CallsTest::testGetCalledByLine(){
	std::cout<<std::endl<<"Testing getCalledByLine..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,1,2);
	myCallsTable.setCalls(1,2,3);
	myCallsTable.setCalls(2,3,1);
	myCallsTable.setCalls(2,4,3);
	myCallsTable.setCalls(3,5,1);
	myCallsTable.setCalls(3,6,2);

	//Get called procedure by line 1,6,7
	CPPUNIT_ASSERT_EQUAL(2, myCallsTable.getCalledByLine(1));
	CPPUNIT_ASSERT_EQUAL(2, myCallsTable.getCalledByLine(6));
	CPPUNIT_ASSERT_EQUAL(-1, myCallsTable.getCalledByLine(7));
}
void CallsTest::testGetCallerOf(){
	std::cout<<std::endl<<"Testing getCallerOf..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,1,2);
	myCallsTable.setCalls(1,2,3);
	myCallsTable.setCalls(2,3,1);
	myCallsTable.setCalls(2,4,3);
	myCallsTable.setCalls(3,5,1);
	myCallsTable.setCalls(3,6,2);

	//Get caller of procedure 1
	Type::Index::Proc callerProcSamplec1[] = {2,3};
	Type::List::Proc callerProcListSample1 (callerProcSamplec1, callerProcSamplec1 + sizeof(callerProcSamplec1)/sizeof(Type::Index::Line));
	Type::List::Proc callerProcList1 = myCallsTable.getCallerOf(1);
	sort(callerProcList1.begin(),callerProcList1.end());
	CPPUNIT_ASSERT(callerProcListSample1==callerProcList1);

	//Get caller of procedure 2
	Type::Index::Proc callerProcSamplec2[] = {1,3};
	Type::List::Proc callerProcListSample2 (callerProcSamplec2, callerProcSamplec2 + sizeof(callerProcSamplec2)/sizeof(Type::Index::Line));
	Type::List::Proc callerProcList2 = myCallsTable.getCallerOf(2);
	sort(callerProcList2.begin(),callerProcList2.end());
	CPPUNIT_ASSERT(callerProcListSample2==callerProcList2);

	//Get caller of procedure 3
	Type::Index::Proc callerProcSamplec3[] = {1,2};
	Type::List::Proc callerProcListSample3 (callerProcSamplec3, callerProcSamplec3 + sizeof(callerProcSamplec3)/sizeof(Type::Index::Line));
	Type::List::Proc callerProcList3 = myCallsTable.getCallerOf(3);
	sort(callerProcList3.begin(),callerProcList3.end());
	CPPUNIT_ASSERT(callerProcListSample3==callerProcList3);
}
void CallsTest::testGetCallerLineOf(){
	std::cout<<std::endl<<"Testing getCallerLineOf..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,1,2);
	myCallsTable.setCalls(1,2,3);
	myCallsTable.setCalls(2,3,1);
	myCallsTable.setCalls(2,4,3);
	myCallsTable.setCalls(3,5,1);
	myCallsTable.setCalls(3,6,2);

	//Get callerLine(which line calls procedure 1)
	Type::Index::Line callerLineSamplec1[] = {3,5};
	Type::List::Line callerLineListSample1 (callerLineSamplec1, callerLineSamplec1 + sizeof(callerLineSamplec1)/sizeof(Type::Index::Line));
	Type::List::Line callerLineList1 = myCallsTable.getCallerLineOf(1);
	sort(callerLineList1.begin(),callerLineList1.end());
	CPPUNIT_ASSERT(callerLineListSample1==callerLineList1);

	//Get callerLine(which line calls procedure 2)
	Type::Index::Line callerLineSamplec2[] = {1,6};
	Type::List::Line callerLineListSample2 (callerLineSamplec2, callerLineSamplec2 + sizeof(callerLineSamplec2)/sizeof(Type::Index::Line));
	Type::List::Line callerLineList2 = myCallsTable.getCallerLineOf(2);
	sort(callerLineList2.begin(),callerLineList2.end());
	CPPUNIT_ASSERT(callerLineListSample2==callerLineList2);

	//Get callerLine(which line calls procedure 3)
	Type::Index::Line callerLineSamplec3[] = {2,4};
	Type::List::Line callerLineListSample3 (callerLineSamplec3, callerLineSamplec3 + sizeof(callerLineSamplec3)/sizeof(Type::Index::Line));
	Type::List::Line callerLineList3 = myCallsTable.getCallerLineOf(3);
	sort(callerLineList3.begin(),callerLineList3.end());
	CPPUNIT_ASSERT(callerLineListSample3==callerLineList3);
}
void CallsTest::testIsCalls(){
	std::cout<<std::endl<<"Testing isCalls..."<<std::endl;
	Calls myCallsTable = Calls::Calls();
	myCallsTable.setCalls(1,1,2);
	myCallsTable.setCalls(1,2,3);
	myCallsTable.setCalls(2,3,1);
	myCallsTable.setCalls(2,4,3);
	myCallsTable.setCalls(3,5,1);
	myCallsTable.setCalls(3,6,2);
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(1,2));
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(1,3));
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(2,1));
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(2,3));
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(3,1));
	CPPUNIT_ASSERT_EQUAL(true, myCallsTable.isCalls(3,2));
	CPPUNIT_ASSERT_EQUAL(false, myCallsTable.isCalls(6,2));
}

